package com.zonski.jbots.wireless.client;

import com.zonski.jbots.engine.Entity;
import com.zonski.jbots.engine.Rectangle;
import com.zonski.jbots.engine.Directions;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.Sprite;

/**
 * Created by IntelliJ IDEA.
 * User: Chris Glover
 * Date: Oct 29, 2003
 * Time: 8:59:34 AM
 * To change this template use Options | File Templates.
 */
public class SpriteEntityRenderer implements EntityRenderer
{
    private Sprite[][][][] images;
    private int updatesPerFrame;
    private int layerOffset;
    private boolean runtoend;

    private static Sprite[][][][] createSprites(Image[][][] modeImages, int maxDirection)
    {
        Sprite[][][][] sprites = new Sprite[modeImages.length][][][];

        for(int m=0; m<modeImages.length; m++)
        {
            Image[][] images = modeImages[m];
            if(images != null)
            {
                sprites[m] = new Sprite[images.length][][];
                for(int i=0; i<images.length; i++)
                {
                    Image[] frames = images[i];
                    Sprite[][] spriteFrames = new Sprite[maxDirection+1][frames.length];
                    for(int j=0; j<frames.length; j++)
                    {
                        Image frame = frames[j];
                        for(int k=0; k<=maxDirection; k++)
                        {
                            Sprite sprite = new Sprite(frame);
                            if(maxDirection > 0)
                            {
                                sprite.setRefPixelPosition(sprite.getWidth()/2, sprite.getHeight()/2);
                                switch(k)
                                {
                                    default:
                                        sprite.setTransform(Sprite.TRANS_ROT180);
                                        break;
                                    case Directions.EAST:
                                        // rotation 90
                                        sprite.setTransform(Sprite.TRANS_ROT90);
                                        break;
                                    case Directions.SOUTH_EAST:
                                    case Directions.SOUTH_WEST:
                                    case Directions.SOUTH:
                                        // do nothing
                                        break;
                                    case Directions.WEST:
                                        sprite.setTransform(Sprite.TRANS_ROT270);
                                        break;
                                }
                            }
                            spriteFrames[k][j] = sprite;
                        }
                        sprites[m][i] = spriteFrames;
                    }
                }
            }
        }
        return sprites;
    }

    public SpriteEntityRenderer(Image[][][] images, int layerOffset, int updatesPerFrame, boolean rotate)
    {
        if(rotate)
        {
            this.images = createSprites(images, Directions.MAX_DIRECTION+1);
        }else{
            this.images = createSprites(images, 0);
        }
        this.layerOffset = layerOffset;
        this.updatesPerFrame = updatesPerFrame;
    }

    public SpriteEntityRenderer(Image image)
    {
        Sprite sprite = new Sprite(image);
        this.images = new Sprite[][][][]{{{{sprite}}}};
        this.layerOffset = 0;
        this.updatesPerFrame = 1;
    }

    public void setRunToEnd(boolean runtoend)
    {
        this.runtoend = runtoend;
    }

    public Sprite getSprite()
    {
        return this.images[0][0][0][0];
    }

    /**
     * renders the entity onto the graphics context
     * @param graphics the graphics context
     * @param entity the entity to render
     */
    public void render(Graphics graphics, Entity entity)
    {
        Sprite[] frames = getFrames(entity);
        if(frames != null)
        {
            int index = getFrameIndex(entity, frames.length);
            Sprite frame = frames[index];
            Rectangle bounds = entity.bounds;
            //frame.setPosition(bounds.getCentreX(), bounds.getCentreY());
            frame.setPosition(bounds.x + (bounds.width - frame.getWidth())/2, bounds.y + (bounds.height - frame.getHeight())/2);
            frame.paint(graphics);
        }
    }

    private final Sprite[] getFrames(Entity entity)
    {
        int mode = entity.getEffectiveMode();
        if(mode >= 0 && mode < this.images.length)
        {
            int layerIndex = entity.layerId - layerOffset;
            Sprite[][][] sprites = images[mode];
            Sprite[] result;
            if(sprites == null)
            {
                result = null;
            }else{
                if(layerIndex < 0 || layerIndex >= sprites.length)
                {
                    layerIndex = 0;
                }
                int direction = entity.direction;
                result = sprites[layerIndex][direction];
            }
            return result;
        }else{
            return null;
        }
    }

    private int getFrameIndex(Entity entity, int length)
    {
        int index;
        if(this.runtoend)
        {
            index = Math.min(entity.getEffectiveModeUpdates() / this.updatesPerFrame, length - 1);
        }else{
            index = (entity.getEffectiveModeUpdates() / this.updatesPerFrame) % (length * 2);
            if(index >= length)
            {
                index = (length * 2) - index - 1;
            }
        }
        return index;
    }
}
